package com.onlyMe.geom
{
	import com.qb9.flashlib.utils.CoordUtil;
	
	public class Coord
	{
		private static const CACHE:Object = {};
		
		public static function create(x:int=0, y:int=0, z:int=0):Coord
		{
			var id:String = x+'_'+y+'_'+z;
			
			return CACHE[id] || (CACHE[id] = new Coord(x, y, z));
		}
		
		public static function fromArray(arr:Array):Coord
		{
			return create(arr[0], arr[1], arr[2]);
		}
		
		protected var _x:int;
		protected var _y:int;
		protected var _z:int;

		public function Coord(x:int = 0, y:int = 0, z:int = 0)
		{
			_x = x;
			_y = y;
			_z = z;
		}

		public function get x():int
		{
			return _x;
		}
		
		public function get y():int
		{
			return _y;
		}

		public function get z():int
		{
			return _z;
		}
		
		public function equals(coord:Coord):Boolean
		{
			return coord === this || x === coord.x && y === coord.y && z === coord.z;
		}
		
		public function add(x:int, y:int, z:int=0):Coord
		{
			return create(_x+x, _y+y, _z+z);
		}

		public function neighbors(coord:Coord):Boolean
		{
			if (equals(coord))
				return false;
				
			return isNeighborValue(x, coord.x) &&
				isNeighborValue(y, coord.y) &&
				isNeighborValue(z, coord.z);
		}
		
		private function isNeighborValue(v1:int, v2:int):Boolean
		{
			return Math.abs(v1 - v2) <= 1;
		}
		
		public function distance(coord:Coord):Number
		{
			return CoordUtil.distance(this, coord);
		}

		public function toString():String
		{
			var arr:Array = toArray();
			if (z === 0)
				arr.pop();
			return '('+arr.join(', ')+')';
		}
		
		public function toArray():Array
		{
			return [x,y,z];
		}
	}
}
